﻿//AcademicPlanner - course registration planning web app.
//Copyright (C) 2009  Boubacar Diallo

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AcademicPlanner.Framework.Helpers
{
	/// <summary>
	/// WidgetHelper provides static helper methods for creating common
	/// html widgets.
	/// </summary>
	/// <since>1.0</since>
	public static class WidgetHelper
	{
		private static int htmlIdCounter = 0;


		/// <summary>
		/// Creates a html message block of a status message indicating success of an action.
		/// </summary>
		/// <param name="pMsg">The status message.</param>
		/// <returns>The html string.</returns>
		/// <seealso cref="M:MessageBlock"/>
		/// <since>1.0</since>
		public static string SuccessMessageBlock(string pMsg)
		{
			return MessageBlock("success", pMsg);
		}

		/// <summary>
		/// Creates a html message block of a status message calling attention 
		/// about the execution of an action.
		/// </summary>
		/// <param name="pMsg">The status message.</param>
		/// <returns>The html string.</returns>
		/// <since>1.0</since>
		public static string InfoMessageBlock(string pMsg)
		{
			return MessageBlock("info", pMsg);
		}

		/// <summary>
		/// Creates a html message block.
		/// </summary>
		/// <param name="pClass">The css class of the message block.</param>
		/// <param name="pMsg">The message.</param>
		/// <returns>The html string.</returns>
		/// <since>1.0</since>
		public static string MessageBlock(string pClass, string pMsg)
		{
			string vTpl = "<div class=\"message {0}\">{1}</div>";
			return string.Format(vTpl, pClass, pMsg);
		}

		/// <summary>
		/// Creates a html block for input errors.
		/// </summary>
		/// <param name="pContent">The content of the block i.e. the input errors.</param>
		/// <param name="pId">The html id of the block.</param>
		/// <param name="pClass">The extra css class of the block.</param>
		/// <returns>The html for the input errors block.</returns>
		/// <since>1.0</since>
		public static string FormErrorsBlock(string pContent, string pId, string pClass)
		{
			string vTpl = "<div id=\"{0}\" class=\"errors-summary {1}\">{2}</div>";
			return string.Format(vTpl, pId, pClass, pContent);
		}

		/// <summary>
		/// Generates html for a side menu dropdown button of actions.
		/// </summary>
		/// <remarks>
		/// This method registers a js script that calls gAcademicPlanControlCtrl.initActionsSideMenu.
		/// </remarks>
		/// <param name="pName">The name of the dropdown button.</param>
		/// <param name="pText">The text of the dropdown button.</param>
		/// <param name="pOptions">The actions in the dropdown button.</param>
		/// <returns>The html string for the dropdown button.</returns>
		/// <since>1.0</since>
		public static string ActionsSideMenu(string pName, string pText, IDictionary<string, string> pOptions)
		{
			var vId = pName + (htmlIdCounter++).ToString();
			var vBuilder = new StringBuilder(string.Format("<input type=\"button\" name=\"{0}\" id=\"{1}\" value=\"{2}\" />",
															pName, vId, pText));
			vBuilder.Append(string.Format("<select id=\"{0}\">", vId + "Select"));
			foreach (var vPair in pOptions)
			{
				vBuilder.Append(string.Format("<option value=\"{0}\">{1}</option>", vPair.Key, vPair.Value));
			}
			vBuilder.Append("</select>");
			vBuilder.Append(string.Format("<script>gDomReadyQueue.push('gAcademicPlanControlCtrl.initActionsSideMenu(\"{0}\", \"{1}\");');</script>", vId, vId + "Select"));

			return vBuilder.ToString();
		}

		/// <summary>
		/// Generates html for a dialog box.
		/// </summary>
		/// <remarks>
		/// This methods registers a js script that calls gDialogsCtrl.create.
		/// </remarks>
		/// <param name="pId">The id of the dialog.</param>
		/// <param name="pHead">The head of the dialog; usually its title.</param>
		/// <param name="pBody">The body of the dialog.</param>
		/// <returns>The html string for the dialog box.</returns>
		/// <since>1.0</since>
		public static string DialogBlock(string pId, string pHead, string pBody)
		{
			var vFormat = "<div id=\"{0}\" class=\"yui-skin-sam hidden\">\n<div class=\"dialog\" id=\"{1}\">\n<div class=\"hd\">{2}</div>\n<div class=\"bd\">{3}</div>\n</div>\n</div>\n<script>gDomReadyQueue.push('gDialogsCtrl.create(\"{4}\")');</script>";
			var rHtml = string.Format(vFormat, pId + "Hider", pId, pHead, pBody, pId);

			return rHtml;
		}

		/// <summary>
		/// Generates html for a context menu of actions.
		/// </summary>
		/// <remarks>
		/// This method generates a js script that calls
		/// gActionsContextMenusCtrl.create.
		/// </remarks>
		/// <param name="pId">The html id of the context menu block.</param>
		/// <param name="pClickHandler">The js function to handle click events on the menu.</param>
		/// <param name="pActions">The list of actions to display.</param>
		/// <param name="pIcons">A list of icons display alongside the actions if necessary.</param>
		/// <returns>The html string for the context menu.</returns>
		/// <since>1.0</since>
		public static string ActionsContextMenu(string pId, string pClickHandler, IList<string> pActions, 
													IList<string> pIcons)
		{
			var vFormat = 
			@"<div id=""{0}"" class=""actions-context-menu hidden"">
				<div class=""bd"">
					<ul>
						<li>
							<a href=""#"" class=""top-link"">{1}</a>
							<div>
								<div class=""bd"">
									<ul>
										{2}
									</ul>
								</div>
							</div>
						</li>
					</ul>
				</div>
			</div>
			<script>gDomReadyQueue.push('gActionsContextMenusCtrl.create(\'{3}\', \'{4}\');');</script>";
			var vBuilder = new StringBuilder();
			var vMenuItemFormat = "<li>\n<a>\n{0}\n{1}</a></li>";

			for (var vI = 0; vI < pActions.Count; vI++)
			{
				vBuilder.Append(string.Format(vMenuItemFormat, 
					(pIcons[vI] != null 
						? HtmlHelperExtensions.Image(UrlHelperExtensions.Icon(pIcons[vI]), pActions[vI]) 
						: ""), pActions[vI]));
			}

			var rHtml = string.Format(vFormat, pId, 
										HtmlHelperExtensions.Image(UrlHelperExtensions.Icon("menu_dropdown.png"), ""), 
										vBuilder.ToString(), pId, pClickHandler);

			return rHtml;
		}

		/// <summary>
		/// Generates pagination links.
		/// </summary>
		/// <param name="pCurrentPage">The current page number.</param>
		/// <param name="pLastPage">The last page number.</param>
		/// <param name="pUrlFormat">The formatted url with a placeholder for the page number.</param>
		/// <param name="pRadius">The number of page links to display before and after the current page.</param>
		/// <returns>The html string for the page links.</returns>
		/// <since>1.0</since>
		public static string PageLinks(int pCurrentPage, int pLastPage, string pUrlFormat, int pRadius)
		{
			if (pLastPage <= 1)
				return "";

			var vBuilder = new StringBuilder("<div class=\"page-links\">");
			var vPagesToPrint = new List<int>();
			var vTmp = pCurrentPage - pRadius - 1;
			var vPrev = pCurrentPage - 1;
			var vNext = pCurrentPage + 1;

			if (pLastPage > 0 && pCurrentPage > 0 && pCurrentPage <= pLastPage)
			{
				while (++vTmp <= (pCurrentPage + pRadius))
				{
					if (vTmp > 0 && vTmp <= pLastPage)
						vPagesToPrint.Add(vTmp);
				}
			}
			if (vPagesToPrint.Count > 0 && vPagesToPrint.First() != 1)
			{
				vBuilder.Append(string.Format("<span class=\"page-link first-page\"><a href=\"{0}\">{1}</a></span>",
									string.Format(pUrlFormat, 1), TranslationHelper.Translate("First", "General")));
			}
			if (vPrev > 0)
			{
				vBuilder.Append(string.Format("<span class=\"page-link previous-page\"><a href=\"{0}\">{1}</a></span>",
									string.Format(pUrlFormat, vPrev), TranslationHelper.Translate("Prev", "General")));
			}
			foreach (var vPage in vPagesToPrint)
			{
				vBuilder.Append(string.Format("<span class=\"page-link nth-page{0}\"><a href=\"{1}\">{2}</a></span>",
					(vPage == pCurrentPage ? " current" : ""), string.Format(pUrlFormat, vPage), vPage));
			}
			if (vNext <= pLastPage)
			{
				vBuilder.Append(string.Format("<span class=\"page-link next-page\"><a href=\"{0}\">{1}</a></span>",
									   string.Format(pUrlFormat, vNext), TranslationHelper.Translate("Next", "General")));
			}
			if (vPagesToPrint.Count > 0 && vPagesToPrint.Last() != pLastPage)
			{
				vBuilder.Append(string.Format("<span class=\"page-link last-page\"><a href=\"{0}\">{1}</a></span>",
									string.Format(pUrlFormat, pLastPage), TranslationHelper.Translate("Last", "General")));
			}
			vBuilder.Append("</div>");

			return vBuilder.ToString();
		}

		/// <summary>
		/// Generates html for a web page tip.
		/// </summary>
		/// <param name="pContent">The content of the page tip.</param>
		/// <returns>The html string for the page tip.</returns>
		/// <since>1.0</since>
		public static string PageTipBlock(string pContent)
		{
			string vTpl = "<div class=\"page-tip\">{0}</div>";
			return string.Format(vTpl, pContent);
		}
	}
}
